﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Game.geodata;
using Game.model;
using java.lang;
using java.util.concurrent;
using lineage2.commons.threading;
using Exception = System.Exception;
using Math = System.Math;
using Object = System.Object;

namespace Game.ai
{
    public class FakePlayerAI:CharacterAI
{
	/**
	 * Field thinking.
	 */
	private volatile int thinking = 0;
	/**
	 * Field _intention_arg0.
	 */
        static Object _intention_arg0 = null;
	/**
	 * Field _intention_arg1.
	 */
        static Object _intention_arg1 = null;
	/**
	 * Field _followTask.
	 */
        static ScheduledFuture _followTask;
	
	/**
	 * Constructor for FakePlayerAI.
	 * @param actor FakePlayer
	 */
	public FakePlayerAI(FakePlayer actor):base(actor)
	{
		//super(actor);
	}
	
	/**
	 * Method changeIntention.
	 * @param intention CtrlIntention
	 * @param arg0 Object
	 * @param arg1 Object
	 */
	
	public override void changeIntention(CtrlIntention intention, Object arg0, Object arg1)
	{
		base.changeIntention(intention, arg0, arg1);
		_intention_arg0 = arg0;
		_intention_arg1 = arg1;
	}
	
	/**
	 * Method setIntention.
	 * @param intention CtrlIntention
	 * @param arg0 Object
	 * @param arg1 Object
	 */
	
	public override void setIntention(CtrlIntention intention, Object arg0, Object arg1)
	{
		_intention_arg0 = null;
		_intention_arg1 = null;
		base.setIntention(intention, arg0, arg1);
	}
	
	/**
	 * Method onEvtThink.
	 */
	
	protected override void onEvtThink()
	{
		FakePlayer actor = getActor();
		if (actor.isActionsDisabled())
		{
			return;
		}
		try
		{
			if (thinking++ > 1)
			{
				return;
			}
			switch (Convert.ToInt32(getIntention()))
			{
				case 1:
					break;
				case 2:
					thinkAttack(true);
					break;
				case 3:
					thinkFollow();
			}
		}
		catch (Exception e)
		{
			_log.error("", e);
		}
		finally
		{
			thinking -= 1;
		}
	}
	
	/**
	 * Method thinkFollow.
	 */
	protected void thinkFollow()
	{
		FakePlayer actor = getActor();
		var target = (Creature) _intention_arg0;
		var offset = (Integer) _intention_arg1;
		if ((target == null) || target.isAlikeDead() || (actor.getDistance(target) > 4000.0D) || (offset == null))
		{
			clientActionFailed();
			return;
		}
		if (actor.isFollow && (actor.getFollowTarget() == target))
		{
			clientActionFailed();
			return;
		}
		if (actor.isInRange(target, offset.intValue() + 20) || actor.isMovementDisabled())
		{
			clientActionFailed();
		}
		if (_followTask != null)
		{
			_followTask.cancel(false);
			_followTask = null;
		}
		_followTask = ThreadPoolManager.getInstance().schedule(new ThinkFollow(), 250L);
	}
	
	/**
	 * Method thinkAttack.
	 * @param checkRange boolean
	 */
	protected void thinkAttack(bool checkRange)
	{
		FakePlayer actor = getActor();
		Player player = actor.getPlayer();
		if (player == null)
		{
			setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
			return;
		}
		if (actor.isActionsDisabled() || actor.isAttackingDisabled())
		{
			return;
		}
		Creature attack_target = getAttackTarget();
		if ((attack_target == null) || (attack_target.isDead()))
		{
			setIntention(CtrlIntention.AI_INTENTION_FOLLOW);
			return;
		}
		if (!checkRange)
		{
			clientStopMoving();
			actor.doAttack(attack_target);
			return;
		}
		int range = actor.getPhysicalAttackRange();
		if (range < 10)
		{
			range = 10;
		}
		bool canSee = GeoEngine.canSeeTarget(actor, attack_target, false);
		if ((!canSee && (range > 200)) || (Math.abs(actor.getZ() - attack_target.getZ()) > 200))
		{
			setIntention(CtrlIntention.AI_INTENTION_FOLLOW);
			return;
		}
		range = (int) (range + actor.getMinDistance(attack_target));
		if (actor.isFakeDeath())
		{
			actor.breakFakeDeath();
		}
		if (actor.isInRangeZ(attack_target, range))
		{
			if (!canSee)
			{
				setIntention(CtrlIntention.AI_INTENTION_FOLLOW);
				return;
			}
			clientStopMoving(false);
			actor.doAttack(attack_target);
		}
	}
	
	/**
	 * Method getActor.
	 * @return FakePlayer
	 */
	
	public override static FakePlayer getActor()
	{
		return (FakePlayer) base.getActor();
	}
	
	/**
	 * @author Mobius
	 */
	public class ThinkFollow:RunnableImpl
	{
		/**
		 * Constructor for ThinkFollow.
		 */

	    public ThinkFollow()
		{
		}
		
		/**
		 * Method runImpl.
		 */
		
		public override void runImpl()
		{
			FakePlayer actor = FakePlayerAI.getActor();
			if (getIntention() != CtrlIntention.AI_INTENTION_FOLLOW)
			{
				return;
			}
			Creature target = (Creature) _intention_arg0;
			int offset = (_intention_arg1 is Integer) ? ((Integer) _intention_arg1).intValue() : 0;
			if ((target == null) || target.isAlikeDead() || (actor.getDistance(target) > 4000.0D))
			{
				setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
				return;
			}
			Player player = actor.getPlayer();
			if ((player == null) || player.isLogoutStarted())
			{
				setIntention(CtrlIntention.AI_INTENTION_ACTIVE);
				return;
			}
			if (!actor.isInRange(target, offset + 20) && (!actor.isFollow || (actor.getFollowTarget() != target)))
			{
				actor.followToCharacter(target, offset, false);
			}
			_followTask = ThreadPoolManager.getInstance().schedule(this, 250L);
		}
	}
}
}
